package com.ruoyi.web.service.consumer;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.ServiceHelper;
import com.ruoyi.common.utils.StrUtils;
import com.ruoyi.common.utils.UserTokenManager;
import com.ruoyi.common.utils.sign.Md5Utils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysCompany;
import com.ruoyi.system.domain.SysConsumer;
import com.ruoyi.system.service.ISysConsumerService;
import com.ruoyi.web.dto.consumer.*;
import com.ruoyi.web.sms.ISmsSender;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class MpConsumerService {

    private final ISysConsumerService consumerService;

    private final ServiceHelper helper;

    private final RedisCache redisCache;

    private final ISmsSender sender;

    public LoginInfo login(AppLoginRequest appLoginRequest) {
        LambdaQueryWrapper<SysConsumer> wrapper = new LambdaQueryWrapper<SysConsumer>()
                .eq(SysConsumer::getPhone, appLoginRequest.getPhone());
        SysConsumer one = consumerService.getOne(wrapper, false);
        if (one == null) {
            throw new RuntimeException("用户不存在");
        }
        if (one.getStatus().equals(2)) {
            throw new RuntimeException("账号已被禁用");
        }
        //md5密码加密
        String password = Md5Utils.hash(appLoginRequest.getPassword());
        if (!password.equals(one.getPassword())) {
            throw new RuntimeException("密码错误!");
        }
        String token = UserTokenManager.generateToken(one.getId(), null);
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setId(one.getId());
        loginInfo.setToken(token);
        return loginInfo;
    }

    /**
     * 注册完成后自动登录
     *
     * @param registerRequest
     * @return
     */
    public LoginInfo register(AppRegisterRequest registerRequest) {
        //查询是否具有该手机号账号
        SysConsumer sysConsumer = consumerService.getOne(new LambdaQueryWrapper<SysConsumer>()
                .eq(SysConsumer::getPhone, registerRequest.getPhone()));
        if (sysConsumer != null) {
            throw new RuntimeException("该手机号已注册,请直接登录");
        }
        if (!registerRequest.getPassword().equals(registerRequest.getConfirmPassword())) {
            throw new RuntimeException("两次密码不一致");
        }
        //查询受邀码存在于本服务器没有
        SysConsumer one = consumerService.getOne(new LambdaQueryWrapper<SysConsumer>()
                .eq(SysConsumer::getCode, registerRequest.getInvitedCode()), false);
        //为空并且不满足内置邀请码
        if (one == null && !"99B64".equals(registerRequest.getInvitedCode())) {
            throw new RuntimeException("邀请码不存在");
        }
        if (verificationCode(registerRequest.getType(), registerRequest.getCaptcha(), registerRequest.getPhone())) {
            SysConsumer consumer = helper.convertToModel(registerRequest, SysConsumer.class);
            String hash = Md5Utils.hash(registerRequest.getPassword());
            consumer.setCreatedTime(LocalDateTime.now())
                    .setContractPhone(registerRequest.getPhone())
                    .setCode(StrUtils.getComplexRandomString(5)) //随机生产邀请码
                    .setPassword(hash);
            if (!consumerService.save(consumer)) {
                throw new RuntimeException("注册失败!");
            }
            String token = UserTokenManager.generateToken(consumer.getId(), null);
            LoginInfo loginInfo = new LoginInfo();
            loginInfo.setId(consumer.getId());
            loginInfo.setToken(token);
            return loginInfo;
        }
        return null;
    }

    /**
     * 发送验证码
     *
     * @param sendAuthCode
     * @param request
     * @return
     */
    public SendAuthCode sendAuthCode(SendAuthCode sendAuthCode, HttpServletRequest request) throws Exception {
        String key = "";
        //首先从redis中获取是否具有当前验证码
        if (!StringUtils.hasLength(sendAuthCode.getPhone())) {
            throw new RuntimeException("请输入手机号!");
        }
        if (!StringUtils.hasLength(sendAuthCode.getType())) {
            throw new RuntimeException("请输入验证码类型!");
        }
        //判断是什么发送验证码是什么类型 此处有验证码注册，验证码更换密码。
        if ("register".equals(sendAuthCode.getType())) {
            //注册账号发送验证码
            key = "register" + "-" + sendAuthCode.getPhone();
            //查询当前用户是否存在
            SysConsumer user = consumerService.getOne(new LambdaQueryWrapper<SysConsumer>()
                    .eq(SysConsumer::getPhone, sendAuthCode.getPhone()), false);
            if (user != null) {
                throw new RuntimeException("该手机号已注册,请直接登录");
            }
        } else if ("changing_the_password".equals(sendAuthCode.getType())) {
            //更换密码注册验证码
            key = "changing_the_password" + "-" + sendAuthCode.getPhone();
        }
        //生成验证码
        String complexRandomString = StrUtils.getRandomString(6);
        Map<String, Object> data = new HashMap<>();
        data.put("code", complexRandomString);
        SendSmsResponse result = sender.sendSms(sendAuthCode.getPhone(), "SMS_259490659", data);
        if (!"OK".equals(result.getCode())) {
            throw new RuntimeException("验证码发送失败：" + result.getMessage());
        }
        redisCache.setCacheObject(key, complexRandomString + ":" + System.currentTimeMillis(), 5, TimeUnit.MINUTES);
        return sendAuthCode;
    }


    private Boolean verificationCode(String type, String code, String phone) {
        //判断验证码是否正确
        String key = "";
        //判断是什么发送验证码是什么类型 此处有验证码注册，验证码更换密码。
        if ("register".equals(type)) {
            //注册账号发送验证码
            key = "register" + "-" + phone;
        } else if ("changing_the_password".equals(type)) {
            //更换密码注册验证码
            key = "changing_the_password" + "-" + phone;
        }
        Object rCode = redisCache.getCacheObject(key);
        if (rCode == null) {
            throw new RuntimeException("验证码已过期!");
        } else {
            String code1 = rCode.toString().split(":")[0];
            if (!code.equals(code1)) {
                throw new RuntimeException("验证码错误!");
            } else {
                redisCache.deleteObject(key);//删除验证码
                return true; //全部通过就返回验证
            }
        }
    }

    /**
     * 获取用户信息
     *
     * @param userId
     * @return
     */
    public SysConsumer getUserInfo(Long userId) {
        SysConsumer consumer = consumerService.getById(userId);
        return consumer;
    }

    /**
     * 修改密码
     *
     * @param updatePassword
     * @param userId
     * @return
     */
    public UpdatePassword updatePwd(UpdatePassword updatePassword, Long userId) {
        if (!updatePassword.getConfirmPassword().equals(updatePassword.getNewPassword())) {
            throw new RuntimeException("两次密码不一致");
        }
        SysConsumer sysConsumer = consumerService.getById(userId);
        boolean matches = Md5Utils.hash(updatePassword.getOldPassword()).equals(sysConsumer.getPassword());
        if (!matches) {
            throw new RuntimeException("原密码错误");
        }
        sysConsumer.setPassword(Md5Utils.hash(updatePassword.getNewPassword()));
        if (!consumerService.updateById(sysConsumer)) {
            throw new RuntimeException("修改密码失败");
        }
        return updatePassword;
    }

    /**
     * 管理员下的用户列表
     *
     * @param keyword
     * @param page
     * @param limit
     * @return
     */
    public TableDataInfo getList(String keyword, Integer page, Integer limit, Integer companyId) {
        TableDataInfo result = new TableDataInfo();
        LambdaQueryWrapper<SysConsumer> wrapper = new LambdaQueryWrapper<>();
        if (!com.ruoyi.common.utils.StringUtils.isNotEmpty(keyword)) {
            wrapper.like(SysConsumer::getUserName, keyword);
        }
        wrapper.orderByDesc(SysConsumer::getCreatedTime);
        if (companyId != null) {
            wrapper.eq(SysConsumer::getCompanyId, companyId);
        }
        Page<SysConsumer> consumerPage = consumerService.page(new Page<>(page, limit), wrapper);
        result.setTotal(consumerPage.getTotal());
        result.setRows(consumerPage.getRecords());
        return result;
    }

    /**
     * 添加用户信息
     *
     * @param consumer
     * @return
     */
    public SysConsumer save(ConsumerRequest consumer) {
        SysConsumer sysConsumer = helper.convertToModel(consumer, SysConsumer.class);
        String hash = Md5Utils.hash(consumer.getPassword());
        sysConsumer.setCreatedTime(LocalDateTime.now())
                .setContractPhone(consumer.getPhone())
                .setCode(StrUtils.getComplexRandomString(5)) //随机生产邀请码
                .setPassword(hash);
        if (!consumerService.save(sysConsumer)) {
            throw new RuntimeException("添加用户失败");
        }
        return sysConsumer;
    }

    /**
     * 修改用户信息
     *
     * @param consumer
     * @return
     */
    public SysConsumer update(ConsumerRequest consumer) {
        if (consumer.getId() == null) {
            throw new RuntimeException("用户id不存在");
        }
        SysConsumer consumerSave = consumerService.getById(consumer.getId());
        if (consumerSave == null) {
            throw new RuntimeException("用户不存在");
        }
        consumerSave.setContractPhone(consumer.getPhone())
                .setIdCard(consumer.getIdCard())
                .setIdCardImg(consumer.getIdCardImg())
                .setIdCardHand(consumer.getIdCardHand())
                .setUpdatedTime(LocalDateTime.now());
        if (!consumerService.updateById(consumerSave)) {
            throw new RuntimeException("修改用户失败");
        }
        return consumerSave;
    }

    /**
     * 禁用用户
     *
     * @param consumer
     * @return
     */
    public SysConsumer ban(SysConsumer consumer) {
        if (consumer.getId() == null) {
            throw new RuntimeException("用户id不存在");
        }
        SysConsumer consumerSave = consumerService.getById(consumer.getId());
        if (consumerSave == null) {
            throw new RuntimeException("用户不存在");
        }
        if (consumerSave.getStatus().equals(2)) {
            throw new RuntimeException("用户已是禁用状态");
        }
        consumerSave.setStatus(2);
        if (!consumerService.updateById(consumerSave)) {
            throw new RuntimeException("禁用用户失败");
        }
        return consumerSave;
    }

    /**
     * 审核用户
     *
     * @param consumer
     * @return
     */
    public SysConsumer audit(SysConsumer consumer) {
        if (consumer.getId() == null) {
            throw new RuntimeException("用户id不存在");
        }
        SysConsumer consumerSave = consumerService.getById(consumer.getId());
        if (consumerSave == null) {
            throw new RuntimeException("用户不存在");
        }
        consumerSave.setStatus(consumer.getStatus());
        consumerSave.setRemark(consumer.getRemark());
        if (!consumerService.updateById(consumerSave)) {
            throw new RuntimeException("审核用户失败");
        }
        return consumerSave;
    }


}
